package com.lonefennec.chameleon.characters;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.utils.Disposable;
import com.lonefennec.chameleon.ChameleonGame;
import com.lonefennec.chameleon.Physics;

public class Player extends WalkingActor implements Disposable
{	
	@Override
	public Actor hit(float x, float y)
	{
		return null;
	}
	
	boolean hasJumped = true;
	
	//group to spawn tongues in
	private Group tongueGroup;
	private Tongue tongue;
	
	private Stage uiStage;
	
	public void setTongue(Tongue tongue)
	{
		this.tongue = tongue;
	}
	
	public void act(float delta)
	{
		super.act(delta);
		
		body.setGravityScale(1);
		
		// tongue grapple
		boolean tonguePressed = Gdx.input.isTouched()
				&& uiStage.getTouchFocus(0) == null; //only if no touch input on UI
		if (tonguePressed)
		{
			// tongue end - at the mouse cursor/touch pos
			Vector2 inputTarget = new Vector2();
			stage.toStageCoordinates(Gdx.input.getX(), Gdx.input.getY(),
					inputTarget);
			
			// flip the sprite if we fired the tongue left
			setSpriteFlipped(inputTarget.x < x);
			
			// tongue start - at the mouth
			Vector2 mouthPos = new Vector2(0.62f, -0.10f);
			if (isSpriteFlipped())
				mouthPos.x = -mouthPos.x;
			
			mouthPos.x += x;
			mouthPos.y += y;
			
			if (tongue != null)
			{
				// existing tongue - just update the start point, end point
				// doesn't change
				
				tongue.start.set(mouthPos);
			} else
			{
				// no existing tongue - create it and fire a ray to determine
				// where to end it
				
				tongue = new Tongue(this, mouthPos, inputTarget);
				tongueGroup.addActor(tongue);
			}
		} else
		{
			if (tongue != null)
			{
				tongueGroup.removeActor(tongue);
				tongue = null;
				
				// force a wake up, in case we fell asleep while grappled onto
				// something
				body.setAwake(true);
			}
		}
		
		// if the tongue is attached, pull towards it, otherwise move normally
		if (tongue != null && tongue.isGrappled())
		{
			body.setGravityScale(0);
			
			isJumping = false;
			isWalking = false;
			hasJumped = true;
			
			float minPull = 0.5f;
			float dist = tongue.start.dst(tongue.finish);
			
			if (dist > minPull)
			{
				float pullSpeed = 10;
				Vector2 pullDirection = tongue.finish.cpy().sub(tongue.start)
						.nor();
				pullDirection.mul(pullSpeed);
				
				body.setLinearVelocity(pullDirection);
			} else
			{
				body.setLinearVelocity(Vector2.Zero);
			}
		} else
		{
			boolean jumpPressed = Gdx.input.isKeyPressed(Keys.SPACE)
					|| ChameleonGame.buttonInput.isJump();
			boolean onGround = isOnGround();
			
			if (onGround && jumpPressed && !hasJumped)
			{
				isJumping = true;
				hasJumped = true;
			} else
			{
				isJumping = false;
				
				if (!jumpPressed && onGround)
				{
					// must be on the ground to reset the jump var - prevents
					// bunny hopping
					hasJumped = false;
				}
			}
			
			final float PLAYER_WALKSPEED = 5.0f;
			
			boolean leftPressed = Gdx.input.isKeyPressed(Keys.A)
					|| ChameleonGame.buttonInput.isLeft();
			boolean rightPressed = Gdx.input.isKeyPressed(Keys.D)
					|| ChameleonGame.buttonInput.isRight();
			
			if (leftPressed)
			{
				isWalking = true;
				walkSpeed = -PLAYER_WALKSPEED;
				
				setSpriteFlipped(true);
			} else if (rightPressed)
			{
				isWalking = true;
				walkSpeed = PLAYER_WALKSPEED;
				
				setSpriteFlipped(false);
			} else
				isWalking = false;
			
			doWalk();
		}
	}
	
	/**
	 * @param tongueGroup
	 * Which group to spawn the tongue object in
	 * @param uiStage
	 * The UI stage - this class handles player input and needs to ignore it if
	 * the UI stage has something touched
	 */
	public Player(Group tongueGroup, Stage uiStage)
	{
		super("sprites/idle.png", 1.28f, 0.64f, 85.0f);
		
		this.tongueGroup = tongueGroup;
		this.uiStage = uiStage;
		
		drawOffsetY = -0.05f;
	}
	
	@Override
	public void dispose()
	{
		Physics.getWorld().destroyBody(body);
	}
}
